package com.linzt.candy.gen.code;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.converts.OracleTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.linzt.candy.common.core.utils.DateUtils;
import com.linzt.candy.common.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author linzt
 * @Date 2020/12/219:48 下午
 * @Description 代码生成
 * @Version 1.0
 */
public class CodeGenerator {

    private static Logger log = LoggerFactory.getLogger(CodeGenerator.class);

    private static final String JDBC_USER_NAME = "root";
    private static final String JDBC_PASSWORD = "Wjy@12345.";
    private static final String AUTHOR = "linzt";

    /**
     * 表名，可以设置多个，通过英文逗号分隔
     * 数据库用户密码，必须使用表的所有者（Owner）
     */
    private static final String tables = "tb_wx_mp,tb_wx_mp_article,tb_wx_mp_material,tb_wx_mp_menu,tb_wx_mp_template_msg,tb_wx_mp_template_send,tb_wx_mp_user";
    /**
     * 模块名称，分业务，不要漏最后面一个点
     */
    private static final String moduleName = "wxmp.";

    /**
     * 表名前缀
     */
    private static final String tablePrefix = "";

    /**
     * 代码生成器的配置常量
     */
    private static final String outPutDir = "/src/main/java";

    /**
     * 1-Oracle：jdbc:oracle:thin:@192.168.110.2:1521:ORAPLAN
     * 2-mysql：jdbc:mysql://localhost:3306/mydbone?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&pinGlobalTxToPhysicalConnection=true&autoReconnect=true
     */
    private static final String jdbcUrl = "jdbc:mysql://47.114.99.4:3306/candy-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
    /**
     * 1-oracle.jdbc.OracleDriver
     * 2-oracle.jdbc.driver.OracleDriver
     * 3-com.mysql.cj.jdbc.Driver
     * 4-com.mysql.jdbc.Driver
     */
    private static final String jdbcDriverClassName = "com.mysql.cj.jdbc.Driver";

    private static final String parentPackage = "com.linzt.candy";
    /**
     * 作者
     */
    private static final String authorName = AUTHOR;
    /**
     * dao文件命名格式
     */
    private static final String mapperPattern = "%sDao";
    private static final String mapperName = moduleName + "dao";
    private static final String xmlName = mapperName;

    /**
     * Service文件命名格式
     */
    private static final String serviceNameNotHasInterfacePattern = "%sService";
    private static final String serviceNameHasInterfacePattern = "Service";
    private static final String serviceName = moduleName + "service";
    private static final String implName = moduleName + "service.impl";
    private static final String pojoName = moduleName + "entity";
    private static final String controllerName = moduleName + "controller";
    /**
     * projectPath拿到的是Demo路径，把outPutDir设置成/test1即可
     */
    private static final String projectPath = System.getProperty("user.dir");

    public static void generator() {

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        log.info("代码输出地址为:{}", projectPath + outPutDir);
        gc.setOutputDir(projectPath + outPutDir);
        gc.setAuthor(authorName);
        gc.setBaseResultMap(true);
        gc.setBaseColumnList(true);
        // 覆盖生成的文件
        gc.setFileOverride(true);
        gc.setServiceName(serviceNameNotHasInterfacePattern);
        gc.setMapperName(mapperPattern);
        /**
         * 是否在xml中添加二级缓存配置：false不生成
         */
        gc.setEnableCache(false);
        /**
         * true:生成文件后，自动打开文件夹
         */
        gc.setOpen(false);
        /**
         * 设置时间类型
         */
        gc.setDateType(DateType.ONLY_DATE);
        /**
         * 设置生成Swagger2 Api注解
         */
        //gc.setSwagger2(true);
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setUrl(jdbcUrl);
        dsc.setDriverName(jdbcDriverClassName);
        dsc.setUsername(JDBC_USER_NAME);
        dsc.setPassword(JDBC_PASSWORD);
        // dsc.setSchemaName("public");
        PackageConfig pc = new PackageConfig();
        pc.setParent(parentPackage);
        pc.setMapper(mapperName);
        pc.setEntity(pojoName);
        pc.setService(serviceName);
        pc.setController(controllerName);
        pc.setServiceImpl(implName);
        pc.setXml(xmlName);

        /**
         * 策略配置
         */
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        /**
         * 设置Lombok模式
         */
        strategy.setEntityLombokModel(false);//
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(false);
        strategy.setTablePrefix("tb_");
        /**
         * 1-公共父类
         * 2-strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
         * 3-写于父类中的公共字段
         * 4-strategy.setSuperEntityColumns("id");
         */
        strategy.setControllerMappingHyphenStyle(true);
        if (!StringUtils.isBlank(tablePrefix)) {
            strategy.setTablePrefix(tablePrefix);
        }
        //strategy.entityTableFieldAnnotationEnable(true);
        strategy.setEntityTableFieldAnnotationEnable(true);
        /**
         * Oracle数据，表名一定要大写，且表名要对应创建的用户，否则不生成代码
         */
        strategy.setInclude(tables.toUpperCase().split(","));
        /**
         * 自定义继承的Controller类全称，带包名,没有就不用设置!
         */
        strategy.setSuperControllerClass("com.linzt.candy.common.core.web.controller.BaseController");
        /**
         * 你自己的父类实体,没有就不用设置!
         */
        strategy.setSuperEntityClass("com.linzt.candy.common.core.web.domain.BaseEntity");
        InjectionConfig injectionConfig = new InjectionConfig() {

            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        mpg.setGlobalConfig(gc);
        mpg.setDataSource(dsc);
        mpg.setPackageInfo(pc);
        mpg.setStrategy(strategy);
        mpg.setCfg(injectionConfig);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
        log.info("代码生成已经完成。" + DateUtils.parseDateToStr("yyyy-MM-dd", new Date()));
    }

    /**
     * 获取数据源配置
     *
     * @param dsc
     */
    private void getDsc(DataSourceConfig dsc) {
        //设置类型转换，默认不太好
        //这个是Oracle的
        dsc.setTypeConvert(new OracleTypeConvert() {

            @Override
            public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
                String fileTypeLower = fieldType.toLowerCase();
                if (fileTypeLower.contains("number")) {
                    //System.out.println("fileTypeLower = " + fileTypeLower);

                    if (fileTypeLower.equals("number")) {//默认长度为38位，占用22个字节空间
                        return DbColumnType.LONG;
                    }
                    if (fileTypeLower.contains(",")) {
                        return DbColumnType.DOUBLE;
                    } else {
                        String num = null;
                        // Str.getNumberText(fileTypeLower);
                        int numInt = Integer.parseInt(num);
                        if (numInt == 1) {
                            return DbColumnType.BYTE;
                        }
                        if (numInt > 1 && numInt <= 4) {
                            return DbColumnType.SHORT;
                        }
                        if (numInt > 4 && numInt <= 9) {
                            return DbColumnType.INTEGER;
                        }
                        if (numInt > 9 && numInt <= 18) {
                            return DbColumnType.LONG;
                        }
                        if (numInt > 18) {
                            return DbColumnType.BIG_DECIMAL;
                        }
                        return DbColumnType.LONG;
                    }
                }
                return super.processTypeConvert(globalConfig, fieldType);
            }
        });

    }


    public static void main(String[] args) {
        generator();
    }

}
